<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>场景与角色移动优化</title>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      font-family: 'Arial', sans-serif;
      overflow: hidden;
      background: #1a1a2e;
    }
    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 20px;
    }
    header {
      text-align: center;
      margin-bottom: 20px;
      color: #fff;
    }
    h1 {
      font-size: 2.5rem;
      margin-bottom: 10px;
      color: #ffcc00;
      text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
    }
    .instructions {
      background: rgba(255, 255, 255, 0.1);
      padding: 15px;
      border-radius: 8px;
      margin-bottom: 20px;
      color: #fff;
    }
    .game-container {
      display: flex;
      gap: 20px;
    }
    .game-wrapper {
      flex: 1;
      height: 500px;
      border: 3px solid #4a4a6a;
      border-radius: 10px;
      overflow: hidden;
      position: relative;
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
    }
    .mh-container {
      width: 100%;
      height: 100%;
      position: relative;
      overflow: hidden;
    }
    .mh-scene {
      width: 4000px;
      height: 2000px;
      background: linear-gradient(45deg, #2ecc71, #3498db);
      position: absolute;
      left: 0;
      top: 0;
      transition: transform 0.5s ease;
      cursor: pointer;
    }
    .grid-overlay {
      position: absolute;
      top: 0;
      left: 0;
      width: 4000px;
      height: 2000px;
      background-image: 
        linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),
        linear-gradient(90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px);
      background-size: 50px 50px;
      pointer-events: none;
    }
    .mh-role {
      width: 60px;
      height: 60px;
      border-radius: 50%;
      background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      box-shadow: 0 0 20px red;
      display: flex;
      justify-content: center;
      align-items: center;
      font-weight: bold;
      color: #fff;
      text-shadow: 1px 1px 2px #000;
    }
    .control-panel {
      width: 300px;
      background: rgba(40, 40, 60, 0.8);
      padding: 15px;
      border-radius: 10px;
      color: #fff;
    }
    .control-panel h2 {
      margin-bottom: 15px;
      color: #ffcc00;
      text-align: center;
    }
    .status-info {
      margin-bottom: 20px;
      padding: 10px;
      background: rgba(0, 0, 0, 0.3);
      border-radius: 5px;
    }
    .status-info p {
      margin: 8px 0;
      font-size: 14px;
    }
    .coordinates {
      font-family: monospace;
    }
    .boundary-info {
      color: #ff9966;
    }
    .controls {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
    }
    .btn {
      padding: 10px;
      border: none;
      border-radius: 5px;
      background: linear-gradient(to bottom, #6b6b8c, #4a4a6a);
      color: white;
      cursor: pointer;
      transition: all 0.2s;
    }
    .btn:hover {
      background: linear-gradient(to bottom, #7b7b9c, #5a5a7a);
      transform: translateY(-2px);
    }
    .btn:active {
      transform: translateY(0);
    }
    .center-btn {
      grid-column: span 2;
      background: linear-gradient(to bottom, #e65c00, #f9d423);
    }
    .click-indicator {
      position: absolute;
      width: 20px;
      height: 20px;
      border-radius: 50%;
      background: rgba(255, 0, 0, 0.5);
      transform: translate(-50%, -50%);
      pointer-events: none;
      z-index: 10;
      animation: clickEffect 0.5s ease-out forwards;
    }
    @keyframes clickEffect {
      0% {
        width: 0;
        height: 0;
        opacity: 0.7;
      }
      100% {
        width: 40px;
        height: 40px;
        opacity: 0;
      }
    }
  </style>
</head>
<body>
  <div id="app" class="container">
    <header>
      <h1>场景与角色移动优化</h1>
      <div class="instructions">
        <p>点击场景任意位置，角色会保持居中，场景会反向移动。边界检测功能会防止场景移动出界。</p>
      </div>
    </header>
    
    <div class="game-container">
      <div class="game-wrapper">
        <div class="mh-container" @click="sceneClick">
          <div 
            class="mh-scene" 
            :style="{
              transform: `translate(${position.x}px, ${position.y}px)`,
            }"
          >
            <div class="grid-overlay"></div>
          </div>
          <div class="mh-role">角色</div>
          <div 
            v-if="showClickIndicator" 
            class="click-indicator" 
            :style="{
              left: `${clickPosition.x}px`,
              top: `${clickPosition.y}px`
            }"
          ></div>
        </div>
      </div>
      
      <div class="control-panel">
        <h2>控制面板</h2>
        <div class="status-info">
          <p>场景坐标: <span class="coordinates">({{ position.x }}, {{ position.y }})</span></p>
          <p>点击坐标: <span class="coordinates">({{ clickPosition.x }}, {{ clickPosition.y }})</span></p>
          <p>边界状态: <span class="boundary-info">{{ boundaryStatus }}</span></p>
        </div>
        <div class="controls">
          <button class="btn" @click="move(-100, 0)">左移</button>
          <button class="btn" @click="move(100, 0)">右移</button>
          <button class="btn" @click="move(0, -100)">上移</button>
          <button class="btn" @click="move(0, 100)">下移</button>
          <button class="btn center-btn" @click="resetPosition">重置位置</button>
        </div>
      </div>
    </div>
  </div>

  <script>
    const { createApp, ref, reactive, onMounted } = Vue;
    
    createApp({
      setup() {
        const position = reactive({
          x: 0,
          y: 0
        });
        
        const clickPosition = reactive({
          x: 0,
          y: 0
        });
        
        const showClickIndicator = ref(false);
        const boundaryStatus = ref('正常');
        
        // 场景尺寸
        const sceneWidth = 4000;
        const sceneHeight = 2000;
        
        // 获取视图尺寸
        const getViewportDimensions = () => {
          return {
            width: document.querySelector('.mh-container')?.offsetWidth || 800,
            height: document.querySelector('.mh-container')?.offsetHeight || 500
          };
        };
        
        // 边界检测
        const checkBoundaries = (x, y) => {
          const viewport = getViewportDimensions();
          let status = '正常';
          
          // 计算最大可移动范围（负值）
          const maxX = -(sceneWidth - viewport.width);
          const maxY = -(sceneHeight - viewport.height);
          
          // 限制在边界内
          const newX = Math.min(Math.max(x, maxX), 0);
          const newY = Math.min(Math.max(y, maxY), 0);
          
          // 设置边界状态
          if (newX !== x || newY !== y) {
            status = '已到达边界';
          }
          
          return { x: newX, y: newY, status };
        };
        
        // 场景点击事件
        const sceneClick = (e) => {
          const container = e.currentTarget;
          const rect = container.getBoundingClientRect();
          
          // 计算点击位置相对于容器的坐标
          clickPosition.x = e.clientX - rect.left;
          clickPosition.y = e.clientY - rect.top;
          
          // 显示点击指示器
          showClickIndicator.value = true;
          setTimeout(() => {
            showClickIndicator.value = false;
          }, 500);
          
          // 计算移动方向（反向移动场景，使角色看起来在移动）
          const viewport = getViewportDimensions();
          const targetX = position.x - (clickPosition.x - viewport.width / 2);
          const targetY = position.y - (clickPosition.y - viewport.height / 2);
          
          // 应用边界检测
          const boundedPos = checkBoundaries(targetX, targetY);
          position.x = boundedPos.x;
          position.y = boundedPos.y;
          boundaryStatus.value = boundedPos.status;
        };
        
        // 移动函数
        const move = (deltaX, deltaY) => {
          const targetX = position.x + deltaX;
          const targetY = position.y + deltaY;
          
          // 应用边界检测
          const boundedPos = checkBoundaries(targetX, targetY);
          position.x = boundedPos.x;
          position.y = boundedPos.y;
          boundaryStatus.value = boundedPos.status;
        };
        
        // 重置位置
        const resetPosition = () => {
          position.x = 0;
          position.y = 0;
          boundaryStatus.value = '已重置';
        };
        
        return {
          position,
          clickPosition,
          showClickIndicator,
          boundaryStatus,
          sceneClick,
          move,
          resetPosition
        };
      }
    }).mount('#app');
  </script>
</body>
</html>